//
//  BRDF.cpp
//  RayTracer
//
//  Created by 俞云康 on 2/22/16.
//  Copyright © 2016 yushroom. All rights reserved.
//

#include "BxDF.hpp"

Color SpecularReflection::sample_f(const Direction& woL, Direction* wiL, const Sample& sample, float*pdf) const {
    *wiL = Direction(-woL.x, -woL.y, woL.z);
    *pdf = 1.f;
    return fresnel->Evaluate(CosTheta(woL)) * R / AbsCosTheta(*wiL);
}

Color SpecularTransmission::sample_f(const Direction& wo_l, Direction* wiL, const Sample& sample, float*pdf) const  {
    // Figure out which η is incident and which is transmitted
    //auto& wo_l = woL;
    bool entering = CosTheta(wo_l) > 0.f;
    float ei = eta_i, et = eta_t;
    if (!entering) {
        std::swap(ei, et);
    }
    
    // Compute transmitted ray direction
    float sin_i2 = SinTheta2(wo_l);
    float eta = ei / et;
    float sin_t2 = eta * eta * sin_i2;
    
    //Handle total internal reflection for transmission
    if (sin_t2 >= 1.f) {
        return Color(0, 0, 0);
    }
    
    float cos_t = sqrtf(std::max(0.f, 1.f - sin_t2));
    if (entering) {
        cos_t = -cos_t;
    }
    float sintOverSini = eta;
    *wiL = Direction(sintOverSini*-wo_l.x, sintOverSini*-wo_l.y, cos_t);
    *pdf = 1.f;
    Color F = fresnel.Evaluate(CosTheta(wo_l));
    return (Color(1, 1, 1)-F)*T / AbsCosTheta(*wiL);
}